#include "texturewidget.h"

const char * TextureWidget::fCgProgramName = "05_texture_sampling";
const char * TextureWidget::fCgVertexProgramFileName = "C3E2v_varying.cg";
const char * TextureWidget::fCgVertexProgramName = "C3E2v_varying";
const char * TextureWidget::fCgFragmentProgramFileName= "C3E2f_texture.cg";
const char * TextureWidget::fCgFragmentProgramName = "C3E2f_texture";

const GLubyte TextureWidget::fDemonTextureData[3*128*128] = {
#include "demon_image.h"
};

TextureWidget::TextureWidget(QWidget *parent)
	: QGLWidget(parent)
{

}

TextureWidget::~TextureWidget()
{
	cgDestroyProgram(fCgVertexProgram);
	cgDestroyProgram(fCgFragmentProgram);
	cgDestroyContext(fCgContext);
}

void TextureWidget::checkForCgError(const char * situation)
{
	CGerror error;
	const char *str = cgGetLastErrorString(&error);
	if(error != CG_NO_ERROR){
		QString errorInfo = QString("%1 %2 %3").arg(fCgProgramName).arg(situation).arg(str);
		QMessageBox::information(NULL,"cg error",errorInfo);
		exit(1);
	}
}

void TextureWidget::initializeGL()
{
	glClearColor(0.5,0.1,1.0,1.0);
	initTexture();
	initCG();
}

void TextureWidget::resizeGL(int w , int h)
{
	if(h==0)
		h=1;
	glViewport(0,0,w,h);
}

void TextureWidget::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	display();
}

void TextureWidget::display()
{
	//bind texture 
	//glBindTexture(GL_TEXTURE_2D,fTextureEnralId);
	//bind vertex program
	cgGLBindProgram(fCgVertexProgram);
	checkForCgError("binding vertex program");

	//enable vertex profile 
	cgGLEnableProfile(fCgVertexProfile);
	checkForCgError("enable vertex profile");

	//bind fragment program 
	cgGLBindProgram(fCgFragmentProgram);
	checkForCgError("binding fragment program");

	//enable fragment profile
	cgGLEnableProfile(fCgFragmentProfile);
	checkForCgError("enable fragment profile");

	//enable texture parameter 
	cgGLEnableTextureParameter(fCgFragmentParam_decal);
	checkForCgError("enable decal texture");
	drawModel();

	//disable vertex profile
	cgGLDisableProfile(fCgVertexProfile);
	checkForCgError("disable vertex profile");
	//disable fragment profile
	cgGLDisableProfile(fCgFragmentProfile);
	checkForCgError("disable fragment profile");
	//disable texture parameter 
	cgGLDisableTextureParameter(fCgFragmentParam_decal);
	checkForCgError("disable texture parameter");
}


void TextureWidget::initCG()
{
	//creating context 
	fCgContext = cgCreateContext();
	checkForCgError("creating cg context");
	//set debug mode false 
	cgGLSetDebugMode(GL_FALSE);
	cgSetParameterSettingMode(fCgContext,CG_DEFERRED_PARAMETER_SETTING);
	checkForCgError("setting debug mode false and parameter setting mode");
	//selecting vertex profile 
	fCgVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
	cgGLSetOptimalOptions(fCgVertexProfile);
	checkForCgError("selecting vertex  profile");
	//creating vertex program 
	fCgVertexProgram = cgCreateProgramFromFile(fCgContext,CG_SOURCE,fCgVertexProgramFileName,fCgVertexProfile,fCgVertexProgramName,NULL);
	checkForCgError("creating vertex program ");
	//loading vertex program 
	cgGLLoadProgram(fCgVertexProgram);
	checkForCgError("loading vertex program");

	//selecting fragment profile 
	fCgFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
	cgGLSetOptimalOptions(fCgFragmentProfile);
	checkForCgError("selecting fragment profile");
	//creating fragment program 
	fCgFragmentProgram = cgCreateProgramFromFile(fCgContext,CG_SOURCE,fCgFragmentProgramFileName,fCgFragmentProfile,fCgFragmentProgramName,NULL);
	checkForCgError("creating fragment program");
	//loading fragment programe 
	cgGLLoadProgram(fCgFragmentProgram);
	checkForCgError("loading fragment program");

	//get uniform parameter in fragment program 
	fCgFragmentParam_decal = cgGetNamedParameter(fCgFragmentProgram,"decal");
	checkForCgError("getting decal parameter error");
	//set texture parameter 
	cgGLSetTextureParameter(fCgFragmentParam_decal,fTextureId);
	checkForCgError("setting decal 2D texture");

	//get uniform parameter in fragment prorgam 
	fCgFragmentParam_enral = cgGetNamedParameter(fCgFragmentProgram,"enral");
	checkForCgError("getting enral parameter error");
	//set texture parameter
	cgGLSetTextureParameter(fCgFragmentParam_enral,fTextureEnralId);
	checkForCgError("setting enral 2D texture");
}

void TextureWidget::drawModel()
{
	//glBegin(GL_QUADS);
	//glTexCoord2f(0.0,0.0);glVertex3f(-1.0,-1.0,1.0);
	//glTexCoord2f(1.0,0.0);glVertex3f(1.0,-1.0,1.0);
	//glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,1.0);
	//glTexCoord2f(0.0,1.0);glVertex3f(-1.0,1.0,1.0);
	//glColor3f(0.0,1.0,0.0);
	//glTexCoord2f(0.0,0.0);glVertex3f(1.0,-1.0,1.0);
	//glTexCoord2f(1.0,0.0);glVertex3f(1.0,-1.0,-1.0);
	//glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,-1.0);
	//glTexCoord2f(0.0,1.0);glVertex3f(1.0,1.0,1.0);
	//glColor3f(0.0,0.0,1.0);
	//glTexCoord2f(0.0,0.0);glVertex3f(-1.0,1.0,1.0);
	//glTexCoord2f(1.0,0.0);glVertex3f(1.0,1.0,1.0);
	//glTexCoord2f(1.0,1.0);glVertex3f(1.0,1.0,-1.0);
	//glTexCoord2f(0.0,1.0);glVertex3f(-1.0,1.0,-1.0);
	//glEnd();
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0);
	glVertex2f(-0.8, -0.8);
	glTexCoord2f(1, 0);
	glVertex2f(0.8, -0.8);
	glTexCoord2f(1, 1);
	glVertex2f(0.8, 0.8);
	glTexCoord2f(0,1);
	glVertex2f(-0.8,0.8);
	glEnd();
}

void TextureWidget::initTexture()
{
	//read texture data 
	QImage tex , buf;
	if(!buf.load("test.jpg")){
		QImage dummy(128,128,QImage::Format_RGB32);
		dummy.fill(24);
		buf = dummy;
	}
	tex = QGLWidget::convertToGLFormat(buf);
	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
	glGenTextures(1,&fTextureId);
	glBindTexture(GL_TEXTURE_2D,fTextureId);
	//gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGB8,128,128,GL_RGB,GL_UNSIGNED_BYTE,fDemonTextureData);
	//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);

	glTexImage2D(GL_TEXTURE_2D,0,3,tex.width(),tex.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,tex.bits());
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

	glGenTextures(1,&fTextureEnralId);
	glBindTexture(GL_TEXTURE_2D,fTextureEnralId);
	if(!buf.load("enral.jpg")){
		QImage dummy(128,128,QImage::Format_RGB32);
		dummy.fill(12);
		buf = dummy;
	}
	tex = QGLWidget::convertToGLFormat(buf);
	glTexImage2D(GL_TEXTURE_2D,0,3,tex.width(),tex.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,tex.bits());
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);


}